﻿using System;
using System.Collections.Generic;
using System.Linq;
using OdaOperation.Model;
using Teigha.Core;
using Teigha.TD;

namespace OdaOperation.Core.Creators
{
    /// <summary>
    /// GridCreator类继承自BaseCreator类，负责在指定数据库中创建网格
    /// </summary>
    internal class GridCreator : BaseCreator
    {
        /// <summary>
        /// 构造函数，接收一个数据库对象
        /// </summary>
        /// <param name="pDb"></param>
        public GridCreator(OdDbDatabase pDb)
            : base(pDb)
        {
        }

        /// <summary>
        /// 构造函数，接收一个数据库对象和块表对象ID
        /// </summary>
        /// <param name="pDb"></param>
        /// <param name="blockTableId"></param>
        public GridCreator(OdDbDatabase pDb, OdDbObjectId blockTableId)
            : base(pDb, blockTableId)
        {
        }

        /// <summary>
        /// 构造函数，接收一个数据库对象和图层名称
        /// </summary>
        /// <param name="pDb"></param>
        /// <param name="layerName"></param>
        public GridCreator(OdDbDatabase pDb, string layerName)
            : base(pDb, layerName)
        {
        }

        /// <summary>
        /// 构造函数，接收一个数据库对象、块表对象ID和图层名称
        /// </summary>
        /// <param name="pDb"></param>
        /// <param name="blockTableId"></param>
        /// <param name="layerName"></param>
        public GridCreator(OdDbDatabase pDb, OdDbObjectId blockTableId, string layerName)
            : base(pDb, blockTableId, layerName)
        {
        }

        /// <summary>
        /// 创建网格的方法，接收表格大小、原点、x轴和y轴向量作为参数
        /// </summary>
        /// <param name="tableSize"></param>
        /// <param name="origin"></param>
        /// <param name="xAxis"></param>
        /// <param name="yAxis"></param>
        /// <returns></returns>
        public List<OdDbLine> CreateGrid(TableSize tableSize, OdGePoint3d origin, OdGeVector3d xAxis, OdGeVector3d yAxis)
        {
            return CreateGrid(m_blockTableId, m_layerName, tableSize, origin, xAxis, yAxis);
        }

        /// <summary>
        /// 创建网格的方法，接收表格大小、表格数据、原点、x轴和y轴向量作为参数
        /// </summary>
        /// <param name="tableSize"></param>
        /// <param name="tableData"></param>
        /// <param name="origin"></param>
        /// <param name="xAxis"></param>
        /// <param name="yAxis"></param>
        /// <returns></returns>
        /// <exception cref="ArgumentNullException"></exception>
        public List<OdDbLine> CreateGrid(TableSize tableSize, TableData tableData, OdGePoint3d origin, OdGeVector3d xAxis, OdGeVector3d yAxis)
        {
            // 检查表格大小和数据是否匹配
            if (tableSize.Rows.Count == tableData.Count && tableSize.Cols.Count == tableData.Max((TableRow x) => x.Count))
            {
                return CreateGrid(m_blockTableId, m_layerName, tableSize, origin, xAxis, yAxis);
            }

            List<OdDbLine> result = new List<OdDbLine>();
            LineCreator lineCreator = new LineCreator(m_database, m_blockTableId, m_layerName);
            int[,] array = new int[tableSize.Rows.Count, tableSize.Cols.Count];
            int num = 0;
            int num2 = 1;

            // 遍历表格数据
            for (int i = 0; i < tableData.Count; i++)
            {
                num = i;
                int j = 0;
                TableRow tableRow = tableData[i];
                for (int k = 0; k < tableRow.Count; k++)
                {
                    TableItem tableItem = tableRow[k] ?? throw new ArgumentNullException($"第{i}行， 第{k}列 item 不能为空");
                    for (; array[num, j] != 0; j++)
                    {
                    }

                    tableItem.LeftIndex = j;
                    tableItem.TopIndex = i;
                    if (tableItem.RowSpan <= 1 && tableItem.ColSpan <= 1)
                    {
                        array[num, j] = num2++;
                        j++;
                    }
                    else if (tableItem.ColSpan > 1)
                    {
                        for (int l = 0; l < tableItem.ColSpan; l++)
                        {
                            array[num, j] = num2;
                            j++;
                        }

                        num2++;
                    }
                    else if (tableItem.RowSpan > 1)
                    {
                        int num3 = num;
                        for (int m = 0; m < tableItem.RowSpan; m++)
                        {
                            array[num3, j] = num2;
                            num3++;
                        }

                        num2++;
                    }
                }
            }

            int count = tableSize.Rows.Count;
            int count2 = tableSize.Cols.Count;
            double num4 = tableSize.Rows.Sum();

            // 删除空行
            for (int num5 = count - 1; num5 >= 0; num5--)
            {
                int num6 = 0;
                for (int num7 = count2 - 1; num7 >= 0; num7--)
                {
                    num6 += array[num5, num7];
                }

                if (num6 == 0)
                {
                    tableSize.Rows.RemoveAt(num5);
                }
            }

            count = tableSize.Rows.Count;

            // 删除空列
            for (int num8 = count2 - 1; num8 >= 0; num8--)
            {
                int num9 = 0;
                for (int num10 = count - 1; num10 >= 0; num10--)
                {
                    num9 += array[num10, num8];
                }

                if (num9 == 0)
                {
                    tableSize.Cols.RemoveAt(num8);
                }
            }

            count2 = tableSize.Cols.Count;
            double num11 = tableSize.Cols.Sum();
            double num12 = tableSize.Rows.Sum();
            OdGePoint3d odGePoint3d = new OdGePoint3d(origin).Add(yAxis.Mul(num4 - num12));
            origin.set(odGePoint3d.x, odGePoint3d.y, odGePoint3d.z);

            // 创建外框线
            OdGeVector3d vect = new OdGeVector3d(xAxis).Mul(num11);
            lineCreator.CreateLine(odGePoint3d, odGePoint3d.Add(vect));
            vect = new OdGeVector3d(yAxis).Mul(num12);
            lineCreator.CreateLine(odGePoint3d, odGePoint3d.Add(vect));
            odGePoint3d = odGePoint3d.Add(new OdGeVector3d(xAxis).Mul(num11)).Add(new OdGeVector3d(yAxis).Mul(num12));
            vect = new OdGeVector3d(xAxis).Mul(0.0 - num11);
            lineCreator.CreateLine(odGePoint3d, odGePoint3d.Add(vect));
            vect = new OdGeVector3d(yAxis).Mul(0.0 - num12);
            lineCreator.CreateLine(odGePoint3d, odGePoint3d.Add(vect));
            odGePoint3d = new OdGePoint3d(origin);

            // 创建横向网格线
            for (int n = 0; n < count - 1; n++)
            {
                odGePoint3d = odGePoint3d.Add(new OdGeVector3d(yAxis).Mul(tableSize.Rows[n]));
                double num13 = 0.0;
                double num14 = 0.0;
                double scale = 0.0;
                int num15 = -1;
                for (int num16 = 0; num16 < count2; num16++)
                {
                    if (array[n, num16] != array[n + 1, num16])
                    {
                        if (num15 == -1)
                        {
                            num15 = num16;
                            num13 = tableSize.Cols[num16];
                            scale = num14;
                        }
                        else
                        {
                            num13 += tableSize.Cols[num16];
                        }
                    }
                    else if (num15 != -1)
                    {
                        OdGePoint3d odGePoint3d2 = odGePoint3d.Add(new OdGeVector3d(xAxis).Mul(scale));
                        OdGePoint3d end = odGePoint3d2.Add(new OdGeVector3d(xAxis).Mul(num13));
                        lineCreator.CreateLine(odGePoint3d2, end);
                        num15 = -1;
                        scale = num14;
                        num13 = 0.0;
                    }

                    num14 += tableSize.Cols[num16];
                }

                if (num13 != 0.0)
                {
                    OdGePoint3d odGePoint3d3 = odGePoint3d.Add(new OdGeVector3d(xAxis).Mul(scale));
                    OdGePoint3d end2 = odGePoint3d3.Add(new OdGeVector3d(xAxis).Mul(num13));
                    lineCreator.CreateLine(odGePoint3d3, end2);
                }
            }

            odGePoint3d = new OdGePoint3d(origin);

            // 创建纵向网格线
            for (int num17 = 0; num17 < count2 - 1; num17++)
            {
                odGePoint3d = odGePoint3d.Add(new OdGeVector3d(xAxis).Mul(tableSize.Cols[num17]));
                double num18 = 0.0;
                double num19 = 0.0;
                double scale2 = 0.0;
                int num20 = -1;
                for (int num21 = 0; num21 < count; num21++)
                {
                    if (array[num21, num17] != array[num21, num17 + 1])
                    {
                        if (num20 == -1)
                        {
                            num20 = num17;
                            num18 = tableSize.Rows[num21];
                            scale2 = num19;
                        }
                        else
                        {
                            num18 += tableSize.Rows[num21];
                        }
                    }
                    else if (num20 != -1)
                    {
                        OdGePoint3d odGePoint3d4 = odGePoint3d.Add(new OdGeVector3d(yAxis).Mul(scale2));
                        OdGePoint3d end3 = odGePoint3d4.Add(new OdGeVector3d(yAxis).Mul(num18));
                        lineCreator.CreateLine(odGePoint3d4, end3);
                        num20 = -1;
                        scale2 = num19;
                        num18 = 0.0;
                    }

                    num19 += tableSize.Rows[num21];
                }

                if (num18 != 0.0)
                {
                    OdGePoint3d odGePoint3d5 = odGePoint3d.Add(new OdGeVector3d(yAxis).Mul(scale2));
                    OdGePoint3d end4 = odGePoint3d5.Add(new OdGeVector3d(yAxis).Mul(num18));
                    lineCreator.CreateLine(odGePoint3d5, end4);
                }
            }

            return result;
        }

        /// <summary>
        /// 私有方法，用于创建网格
        /// </summary>
        /// <param name="blockTableId"></param>
        /// <param name="layerName"></param>
        /// <param name="tableSize"></param>
        /// <param name="origin"></param>
        /// <param name="xAxis"></param>
        /// <param name="yAxis"></param>
        /// <returns></returns>
        private List<OdDbLine> CreateGrid(OdDbObjectId blockTableId, string layerName, TableSize tableSize, OdGePoint3d origin, OdGeVector3d xAxis, OdGeVector3d yAxis)
        {
            List<OdDbLine> result = new List<OdDbLine>();
            LineCreator lineCreator = new LineCreator(m_database, blockTableId, layerName);
            double scale = tableSize.Cols.Sum();
            double scale2 = tableSize.Rows.Sum();
            OdGePoint3d odGePoint3d = new OdGePoint3d(origin.x, origin.y, origin.z);
            OdGeVector3d vect = new OdGeVector3d(yAxis).Mul(scale2);

            // 创建列线
            foreach (double col in tableSize.Cols)
            {
                lineCreator.CreateLine(odGePoint3d, odGePoint3d.Add(vect));
                odGePoint3d = odGePoint3d.Add(new OdGeVector3d(xAxis).Mul(col));
            }

            lineCreator.CreateLine(odGePoint3d, odGePoint3d.Add(vect));
            odGePoint3d = new OdGePoint3d(origin.x, origin.y, origin.z);
            vect = new OdGeVector3d(xAxis).Mul(scale);

            // 创建行线
            foreach (double row in tableSize.Rows)
            {
                lineCreator.CreateLine(odGePoint3d, odGePoint3d.Add(vect));
                odGePoint3d = odGePoint3d.Add(new OdGeVector3d(yAxis).Mul(row));
            }

            lineCreator.CreateLine(odGePoint3d, odGePoint3d.Add(vect));
            return result;
        }
    }

}